package com.jy.oms.framework.id;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.system.SystemUtil;
import com.jy.oms.framework.init.InitializingService;
import com.jy.oms.framework.util.NetworkUtil;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class IdCreateService implements InitializingService {

    protected RedissonClient redissonClient;
    //工作节点id
    @Value("${snowflake.worker_id:1}")
    private Long workerId;
    @Value(("${snowflake.datacenter.app:}"))
    private String datacenterApp;
    private Snowflake snowflake;
    private final Snowflake defaultSnowflake = new Snowflake(0, 0);

    public IdCreateService(@Autowired(required = false) @Qualifier("redissonClient")
                           RedissonClient redissonClient){
        this.redissonClient = redissonClient;
    }

    @Override
    public void initService(ApplicationContext applicationContext) {
        //k8s部署应用，未固定节点IP; 每个应用集群dataCenterId独立
        RAtomicLong rAtomicLong = redissonClient.getAtomicLong("snowflake.datacenter:" + datacenterApp);
        Long dataCenterId = rAtomicLong.incrementAndGet();
        String ip = NetworkUtil.getLocalhostStr();
        RBucket<Long> bucket = redissonClient.getBucket("snowflake:datacenter:" + ip);
        bucket.set(dataCenterId, 30, TimeUnit.DAYS);

        //本地workerId尽可能不同
        if (!SystemUtil.getOsInfo().isLinux()) {
            Random random = new Random();
            int rWorkerId = random.nextInt(32);
            rWorkerId = workerId.intValue() == rWorkerId ? random.nextInt(rWorkerId) : rWorkerId;
            workerId = Long.valueOf(rWorkerId);
        }

        //每个应用workerId不相同（单独配置）；当应用集群节点数量超过32时，应重新动态设计workerId
        snowflake = new Snowflake(workerId, dataCenterId % 32);
    }

    public Long getId() {
        if(snowflake == null){
            return defaultSnowflake.nextId();
        }
        return snowflake.nextId();
    }

    /**
     * 根据Snowflake的ID，获取生成时间
     *
     * @param id snowflake算法生成的id
     * @return 生成的时间
     */
    public long getGenerateDateTime(long id) {
        return snowflake.getGenerateDateTime(id);
    }

}
